home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / util / asynchttp.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  20KB  |  568 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. __author__ = '\nDownright Software LLC\nhttp://www.downright.com\n'
  5. __copyright__ = "\nCopyright (c) 2001 Downright Software LLC. All Rights Reserved.\n\nDistributed and Licensed under the provisions of the Python Open Source License\nAgreement which is included by reference. (See 'Front Matter' in the latest\nPython documentation)\n\nWARRANTIES\nYOU UNDERSTAND AND AGREE THAT:\n\na. YOUR USE OF THE PACKAGE IS AT YOUR SOLE RISK.  THE PACKAGE IS PROVIDED ON\nAN 'AS IS' AND 'AS AVAILABLE' BASIS.  DOWNRIGHT EXPRESSLY DISCLAIMS ALL\nWARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED\nTO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE\nAND NON-INFRINGEMENT.\n\nb. DOWNRIGHT MAKES NO WARRANTY THAT (1) THE PACKAGE WILL MEET YOUR\nREQUIREMENTS, (2) THE PACKAGE WILL BE UNINTERRUPTED, TIMELY, SECURE, OR\nERROR-FREE, (3) THE RESULTS THAT MAY BE OBTAINED FROM THE USE OF THE PACKAGE\nWILL BE ACCURATE OR RELIABLE, (4) THE OTHER MATERIAL PURCHASED OR OBTAINED BY\nYOU THROUGH THE PACKAGE WILL MEET YOUR EXPECTATIONS,, AND (5) ANY ERRORS IN\nTHE PACKAGE WILL BE CORRECTED.\n\nc. ANY MATERIALS DOWNLOADED OR OTHERWISE OBTAINED THROUGH THE USE OF THE\nPACKAGE IS DONE AT YOUR OWN DISCRETION AND RISK AND THAT YOU WILL BE SOLELY\nRESPONSIBLE FOR ANY DAMAGE TO YOUR COMPUTER SYSTEM OR LOSS OF DATA THAT\nRESULTS FROM THE DOWNLOAD OF ANY SUCH MATERIAL.\n\nd. NO ADVICE OR INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED BY YOU FROM\nDOWNRIGHT OR THROUGH OR FROM THE PACKAGE SHALL CREATE ANY WARRANTY NOT\nEXPRESSLY STATED IN THE TOS.\n\nLIMITATION OF LIABILITY\nYOU EXPRESSLY UNDERSTAND AND AGREE THAT DOWNRIGHT SHALL NOT BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR EXEMPLARY DAMAGES,\nINCLUDING BUT NOT LIMITED TO, DAMAGES FOR LOSS OF PROFITS, GOODWILL, USE,\nDATA OR OTHER INTANGIBLE LOSSES (EVEN IF DOWNRIGHT HAS BEEN ADVISED OF SUCH\nDAMAGES), RESULTING FROM:\n(1) THE USE OR THE INABILITY TO USE THE PACKAGE;\n(2) THE COST OF PROCUREMENT OF SUBSTITUTE GOODS AND SERVICES RESULTING FROM\nANY GOODS, DATA, INFORMATION OR SERVICES PURCHASED OR OBTAINED OR MESSAGES\nRECEIVED OR TRANSACTIONS ENTERED INTO THROUGH OR FROM THE PACKAGE;\n(3) UNAUTHORIZED ACCESS TO OR ALTERATION OF YOUR TRANSMISSIONS OR DATA;\n(4) STATEMENTS OF CONDUCT OF ANY THIRD PARTY ON THE PACKAGE; OR\n(5) ANY OTHER MATTER RELATING TO THE PACKAGE.\n"
  6. __version__ = '0.20'
  7. import sys
  8. import asynchat
  9. import asyncore
  10. import socket
  11. import time
  12. import string
  13. import StringIO
  14. import mimetools
  15. HTTP_PORT = 80
  16. HTTPS_PORT = 443
  17. import common
  18.  
  19. class AsyncHTTPResponse:
  20.     
  21.     def __init__(self, fp, debuglevel = 0):
  22.         self.fp = fp
  23.         self.debuglevel = debuglevel
  24.         self.msg = None
  25.         self._replyline = ''
  26.         self.status = None
  27.         self.reason = None
  28.         self.version = None
  29.  
  30.     
  31.     def _process_response(self):
  32.         self._replyline = self.fp.readline()
  33.         if self.debuglevel > 0:
  34.             print 'reply: %s' % self._replyline
  35.         
  36.         replylist = string.split(self._replyline, None, 2)
  37.         if len(replylist) == 3:
  38.             (version, status, reason) = replylist
  39.         elif len(replylist) == 2:
  40.             (version, status) = replylist
  41.             reason = ''
  42.         else:
  43.             raise BadStatusLine(self._replyline, name = str(self))
  44.         if version[:5] != 'HTTP/':
  45.             raise BadStatusLine(self._replyline, name = str(self))
  46.         
  47.         
  48.         try:
  49.             self.code = self.status = int(status)
  50.         except:
  51.             raise BadStatusLine(self._replyline, name = str(self))
  52.  
  53.         self.reason = string.strip(reason)
  54.         if version == 'HTTP/1.0':
  55.             self.version = 10
  56.         elif version.startswith('HTTP/1.'):
  57.             self.version = 11
  58.         else:
  59.             raise UnknownProtocol(self._replyline, name = str(self))
  60.         self.msg = mimetools.Message(self.fp, 0)
  61.         if self.debuglevel > 0:
  62.             for hdr in self.msg.headers:
  63.                 print 'header: %s' % string.strip(hdr)
  64.             
  65.         
  66.         self.error = self.code // 100 != 2
  67.         self.body = None
  68.  
  69.     
  70.     def __str__(self):
  71.         return 'AsyncHTTPResponse %r' % self._replyline
  72.  
  73.     
  74.     def getheader(self, name, default = None):
  75.         if self.msg is None:
  76.             raise ResponseNotReady(name = str(self))
  77.         
  78.         return self.msg.getheader(name, default)
  79.  
  80.     
  81.     def getbody(self):
  82.         if self.body is None:
  83.             raise ResponseNotReady(name = str(self))
  84.         
  85.         return self.body
  86.  
  87.     
  88.     def read(self, howmuch = -1):
  89.         return self.fp.read(howmuch)
  90.  
  91.     
  92.     def info(self):
  93.         return self.msg
  94.  
  95.  
  96. _CHUNK_REQUEST_SIZE = 8192
  97. _STATE_IDLE = 'asynchttp._STATE_IDLE'
  98. _STATE_CONNECTING = 'asynchttp._STATE_CONNECTING'
  99. _STATE_ACTIVE = 'asynchttp._STATE_ACTIVE'
  100. _STATE_ACCEPTING_HEADERS = 'asynchttp._STATE_ACCEPTING_HEADERS'
  101. _STATE_REQUESTING_BODY = 'asynchttp._STATE_REQUESTING_BODY'
  102. _STATE_CHUNK_START = 'asynchttp._STATE_CHUNK_START'
  103. _STATE_CHUNK_BODY = 'asynchttp._STATE_CHUNK_BODY'
  104. _STATE_CHUNK_RESIDUE = 'asynchttp._STATE_CHUNK_RESIDUE'
  105.  
  106. class AsyncHTTPConnection(common.socket):
  107.     _http_vsn = 11
  108.     _http_vsn_str = 'HTTP/1.1'
  109.     response_class = AsyncHTTPResponse
  110.     default_port = HTTP_PORT
  111.     auto_open = 1
  112.     debuglevel = 0
  113.     
  114.     def __init__(self, host = None, port = None):
  115.         self._TERMINATOR_MAP = {
  116.             _STATE_IDLE: self._no_action,
  117.             _STATE_CONNECTING: self._no_action,
  118.             _STATE_ACTIVE: self._no_action,
  119.             _STATE_ACCEPTING_HEADERS: self._header_data,
  120.             _STATE_REQUESTING_BODY: self._body_data,
  121.             _STATE_CHUNK_START: self._chunk_start_data,
  122.             _STATE_CHUNK_BODY: self._chunk_body_data,
  123.             _STATE_CHUNK_RESIDUE: self._chunk_residue_data }
  124.         self._AsyncHTTPConnection__state = None
  125.         self._AsyncHTTPConnection__set_state(_STATE_IDLE)
  126.         self._headerdict = { }
  127.         self._requestfp = None
  128.         self._responsefp = StringIO.StringIO()
  129.         self._chunkfp = None
  130.         self.response = self.response_class(self._responsefp, self.debuglevel)
  131.         self._set_hostport(host, port)
  132.         self._willclose = 0
  133.         import primitives as primitives
  134.         self._on_connect = primitives.Delegate()
  135.         common.socket.__init__(self, False)
  136.  
  137.     
  138.     def _set_hostport(self, host, port):
  139.         if host and port is None:
  140.             i = string.find(host, ':')
  141.             if i >= 0:
  142.                 port = int(host[i + 1:])
  143.                 host = host[:i]
  144.             else:
  145.                 port = self.default_port
  146.         
  147.         self.host = host
  148.         self.port = port
  149.  
  150.     
  151.     def set_debuglevel(self, level):
  152.         self.debuglevel = level
  153.  
  154.     
  155.     def connect(self):
  156.         self._AsyncHTTPConnection__set_state(_STATE_CONNECTING)
  157.         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
  158.         if self.debuglevel > 0:
  159.             print 'connecting: (%s, %s)' % (self.host, self.port)
  160.         
  161.         import util.net as net
  162.         import socks as socks
  163.         pi = net.GetProxyInfo()
  164.         use_proxy = True
  165.         host = self.host
  166.         port = self.port
  167.         if pi.get('proxytype', 0) == socks.PROXY_TYPE_HTTP:
  168.             use_proxy = False
  169.         
  170.         common.socket.connect(self, (host, port), use_proxy = use_proxy, error = self.handle_error)
  171.  
  172.     
  173.     def close(self):
  174.         if self.debuglevel > 0:
  175.             print 'asynchttp.close() (%s, %s)' % (self.host, self.port)
  176.         
  177.         self.connected = 0
  178.         if self.socket:
  179.             common.socket.close(self)
  180.         
  181.         self._set_hostport(None, None)
  182.  
  183.     
  184.     def send_entity(self, str):
  185.         if self.debuglevel > 0:
  186.             print 'send_entity %r' % str
  187.         
  188.         self._requestfp.write(str)
  189.  
  190.     
  191.     def putrequest(self, method, url):
  192.         if self.debuglevel > 0:
  193.             print 'putrequest %s %s' % (method, url)
  194.         
  195.         if self._AsyncHTTPConnection__state is not _STATE_ACTIVE:
  196.             raise RequestNotReady('Invalid putrequest() %s' % self._AsyncHTTPConnection__state, name = str(self))
  197.         
  198.         self._requestfp = StringIO.StringIO()
  199.         if not url:
  200.             url = '/'
  201.         
  202.         self._requestfp.write('%s %s %s\r\n' % (method, url, self._http_vsn_str))
  203.         if self._http_vsn == 11:
  204.             self.putheader('Host', self.host)
  205.             self.putheader('Accept-Encoding', 'identity')
  206.         
  207.  
  208.     
  209.     def putheader(self, header, value):
  210.         if self.debuglevel > 0:
  211.             print 'putheader %s: %s' % (header, value)
  212.         
  213.         self._headerdict[header] = value
  214.  
  215.     
  216.     def endheaders(self):
  217.         if self._AsyncHTTPConnection__state is not _STATE_ACTIVE:
  218.             self._on_connect += self.endheaders
  219.             return None
  220.         
  221.         if self.debuglevel > 0:
  222.             print 'endheaders'
  223.         
  224.         for header, value in self._headerdict.items():
  225.             self._requestfp.write('%s: %s\r\n' % (header, value))
  226.         
  227.         self._requestfp.write('\r\n')
  228.  
  229.     
  230.     def request(self, method, url, body = None, headers = { }):
  231.         if self.debuglevel > 0:
  232.             print 'request'
  233.         
  234.         if self._AsyncHTTPConnection__state is not _STATE_ACTIVE:
  235.             (None, None, self, self, self._on_connect) += (lambda : self.request(method, url, body, headers))
  236.             return None
  237.         
  238.         self._send_request(method, url, body, headers)
  239.  
  240.     
  241.     def _send_request(self, method, url, body, headers):
  242.         if self.debuglevel > 0:
  243.             print '_send_request'
  244.         
  245.         self.putrequest(method, url)
  246.         if body:
  247.             self.putheader('Content-Length', str(len(body)))
  248.         
  249.         for hdr, value in headers.items():
  250.             self.putheader(hdr, value)
  251.         
  252.         self.endheaders()
  253.         if body:
  254.             self.send_entity(body)
  255.         
  256.  
  257.     
  258.     def getresponse(self):
  259.         if self._AsyncHTTPConnection__state is not _STATE_ACTIVE:
  260.             self._on_connect += self.getresponse
  261.             return self.response
  262.         
  263.         self._AsyncHTTPConnection__set_state(_STATE_ACCEPTING_HEADERS)
  264.         self.push(self._requestfp.getvalue())
  265.         self._requestfp = None
  266.         self.set_terminator('\r\n\r\n')
  267.         return self.response
  268.  
  269.     
  270.     def handle_connect(self):
  271.         self._AsyncHTTPConnection__set_state(_STATE_ACTIVE)
  272.         if self.debuglevel > 0:
  273.             print 'connected: (%s, %s)' % (self.host, self.port)
  274.         
  275.         self._on_connect.call_and_clear()
  276.  
  277.     
  278.     def handle_close(self):
  279.         if self.debuglevel > 0:
  280.             print 'closed by server: (%s, %s) %s' % (self.host, self.port, self._AsyncHTTPConnection__state)
  281.         
  282.         common.socket.handle_close(self)
  283.         self.close()
  284.         if self._AsyncHTTPConnection__state in [
  285.             _STATE_REQUESTING_BODY,
  286.             _STATE_CHUNK_BODY,
  287.             _STATE_CHUNK_RESIDUE]:
  288.             self.found_terminator()
  289.             return None
  290.         
  291.  
  292.     
  293.     def handle_error(self, why = None):
  294.         self._AsyncHTTPConnection__set_state(_STATE_IDLE)
  295.         common.socket.handle_error(self, why)
  296.  
  297.     
  298.     def collect_incoming_data(self, data):
  299.         if not self._responsefp:
  300.             raise UnexpectedData("%s '%s' '%s' '%s'" % (self._AsyncHTTPConnection__state, data, self.get_terminator(), self.ac_in_buffer), name = str(self))
  301.         
  302.         self._responsefp.write(data)
  303.  
  304.     
  305.     def _no_action(self):
  306.         raise UnexpectedTerminator("%s '%s'" % (self._AsyncHTTPConnection__state, self.get_terminator()), name = str(self))
  307.  
  308.     
  309.     def _header_data(self):
  310.         self._responsefp.seek(0)
  311.         self.response._process_response()
  312.         self._willclose = string.lower(self.response.getheader('connection', '')) == 'close'
  313.         transferencoding = string.lower(self.response.getheader('transfer-encoding', ''))
  314.         self._responsefp = StringIO.StringIO()
  315.         if transferencoding:
  316.             if transferencoding == 'chunked':
  317.                 self._chunkfp = StringIO.StringIO()
  318.                 self.set_terminator('\r\n')
  319.                 self._AsyncHTTPConnection__set_state(_STATE_CHUNK_START)
  320.                 return None
  321.             
  322.             raise UnknownTransferEncoding(self.response.getheader('transfer-encoding', ''), name = str(self))
  323.         
  324.         contentlengthstr = self.response.getheader('content-length', None)
  325.         if contentlengthstr:
  326.             contentlength = int(contentlengthstr)
  327.         else:
  328.             contentlength = None
  329.         self.set_terminator(contentlength)
  330.         self._AsyncHTTPConnection__set_state(_STATE_REQUESTING_BODY)
  331.  
  332.     
  333.     def _body_data(self):
  334.         self.response.body = self._responsefp.getvalue()
  335.         self._responsefp = None
  336.         if self._willclose:
  337.             self.close()
  338.         
  339.         self._AsyncHTTPConnection__set_state(_STATE_ACTIVE)
  340.         self.handle_response()
  341.  
  342.     
  343.     def _get_chunk_size(self):
  344.         splitlist = self._chunkbuffer.lstrip().split('\r\n', 1)
  345.         if len(splitlist) == 1:
  346.             chunkline = splitlist[0]
  347.             self._chunkbuffer = ''
  348.         else:
  349.             (chunkline, self._chunkbuffer) = splitlist
  350.         i = string.find(chunkline, ';')
  351.         if i >= 0:
  352.             chunkline = chunkline[:i]
  353.         
  354.         
  355.         try:
  356.             chunksize = string.atoi(chunkline, 16)
  357.         except:
  358.             raise InvalidChunk("Can't compute chunk size from '%s' '%s'" % (chunkline, self._chunkbuffer))
  359.  
  360.         if self.debuglevel > 0:
  361.             print "chunksize = '%d" % chunksize
  362.         
  363.         return chunksize
  364.  
  365.     
  366.     def _chunk_start_data(self):
  367.         self._chunkbuffer = self._responsefp.getvalue()
  368.         self._chunksize = self._get_chunk_size()
  369.         if self._chunksize == 0:
  370.             if self.debuglevel > 0:
  371.                 print '0 size Chunk: ending chunk processing'
  372.             
  373.             self.response.body = self._chunkfp.getvalue()
  374.             self._chunkfp = None
  375.             self.set_terminator('\r\n\r\n')
  376.             self._responsefp = StringIO.StringIO()
  377.             self._AsyncHTTPConnection__set_state(_STATE_CHUNK_RESIDUE)
  378.             return None
  379.         
  380.         self.set_terminator(self._chunksize + 2)
  381.         self._responsefp = StringIO.StringIO()
  382.         self._AsyncHTTPConnection__set_state(_STATE_CHUNK_BODY)
  383.  
  384.     
  385.     def _chunk_body_data(self):
  386.         self._chunkbuffer += self._responsefp.getvalue()
  387.         while self._chunkbuffer:
  388.             chunk_plus_crlf_size = self._chunksize + 2
  389.             if len(self._chunkbuffer) > chunk_plus_crlf_size:
  390.                 chunkbody = self._chunkbuffer[:chunk_plus_crlf_size]
  391.                 self._chunkbuffer = self._chunkbuffer[chunk_plus_crlf_size:]
  392.                 self._chunkbuffer = self._chunkbuffer.lstrip()
  393.             else:
  394.                 chunkbody = self._chunkbuffer
  395.                 self._chunkbuffer = ''
  396.             self._chunkfp.write(chunkbody)
  397.             if not self._chunkbuffer:
  398.                 break
  399.             
  400.             if self._chunkbuffer.find('\r\n') < 0:
  401.                 self._responsefp = StringIO.StringIO()
  402.                 self.set_terminator('\r\n')
  403.                 self._AsyncHTTPConnection__set_state(_STATE_CHUNK_START)
  404.                 return None
  405.             
  406.             self._chunksize = self._get_chunk_size()
  407.             if self._chunksize == 0:
  408.                 if self.debuglevel > 0:
  409.                     print '0 size Chunk: ending chunk processing'
  410.                 
  411.                 self.response.body = self._chunkfp.getvalue()
  412.                 self._chunkfp = None
  413.                 if self._chunkbuffer:
  414.                     self._chunkbuffer = ''
  415.                     self._AsyncHTTPConnection__set_state(_STATE_ACTIVE)
  416.                     if self._willclose:
  417.                         self.close()
  418.                     
  419.                     self.handle_response()
  420.                     return None
  421.                 
  422.                 self.set_terminator('\r\n\r\n')
  423.                 self._responsefp = StringIO.StringIO()
  424.                 self._AsyncHTTPConnection__set_state(_STATE_CHUNK_RESIDUE)
  425.                 return None
  426.             
  427.             chunk_plus_crlf_size = self._chunksize + 2
  428.             bufsize = len(self._chunkbuffer)
  429.             if bufsize < chunk_plus_crlf_size:
  430.                 self.set_terminator(chunk_plus_crlf_size - bufsize)
  431.                 self._responsefp = StringIO.StringIO()
  432.                 self._AsyncHTTPConnection__set_state(_STATE_CHUNK_BODY)
  433.                 return None
  434.                 continue
  435.         self._responsefp = StringIO.StringIO()
  436.         self.set_terminator('\r\n')
  437.         self._AsyncHTTPConnection__set_state(_STATE_CHUNK_START)
  438.  
  439.     
  440.     def _chunk_residue_data(self):
  441.         residue = string.strip(self._responsefp.getvalue())
  442.         if self.debuglevel > 0 and residue:
  443.             print "chunk residue '%s'" % residue
  444.         
  445.         self._responsefp = None
  446.         if self._willclose:
  447.             self.close()
  448.         
  449.         self._AsyncHTTPConnection__set_state(_STATE_ACTIVE)
  450.         self.handle_response()
  451.  
  452.     
  453.     def handle_response(self):
  454.         raise HandleResponse('Call to AsyncHTTPConnection.handle_response', name = str(self))
  455.  
  456.     
  457.     def __set_state(self, next_state):
  458.         if self.debuglevel > 0:
  459.             print '%s to %s' % (self._AsyncHTTPConnection__state, next_state)
  460.         
  461.         self._AsyncHTTPConnection__state = next_state
  462.         self.found_terminator = self._TERMINATOR_MAP[self._AsyncHTTPConnection__state]
  463.  
  464.  
  465.  
  466. class AsyncHTTPException(Exception):
  467.     
  468.     def __init__(self, message = '', name = ''):
  469.         self._message = message
  470.         self._name = name
  471.  
  472.     
  473.     def __str__(self):
  474.         return '%s %s' % (self._name, self._message)
  475.  
  476.  
  477.  
  478. class NotConnected(AsyncHTTPException):
  479.     pass
  480.  
  481.  
  482. class UnknownProtocol(AsyncHTTPException):
  483.     pass
  484.  
  485.  
  486. class UnknownTransferEncoding(AsyncHTTPException):
  487.     pass
  488.  
  489.  
  490. class BadStatusLine(AsyncHTTPException):
  491.     pass
  492.  
  493.  
  494. class ImproperConnectionState(AsyncHTTPException):
  495.     pass
  496.  
  497.  
  498. class RequestNotReady(ImproperConnectionState):
  499.     pass
  500.  
  501.  
  502. class ResponseNotReady(ImproperConnectionState):
  503.     pass
  504.  
  505.  
  506. class HandleResponse(ImproperConnectionState):
  507.     pass
  508.  
  509.  
  510. class UnexpectedData(AsyncHTTPException):
  511.     pass
  512.  
  513.  
  514. class UnexpectedTerminator(AsyncHTTPException):
  515.     pass
  516.  
  517.  
  518. class InvalidChunk(AsyncHTTPException):
  519.     pass
  520.  
  521.  
  522. class __test_AsyncHTTPConnection(AsyncHTTPConnection):
  523.     
  524.     def __init__(self, host, port, url):
  525.         AsyncHTTPConnection.__init__(self, host, port)
  526.         self._url = url
  527.  
  528.     
  529.     def handle_response(self):
  530.         self.close()
  531.  
  532.     
  533.     def handle_connect(self):
  534.         print '__test_AsyncHTTPConnection.handle_connect'
  535.         AsyncHTTPConnection.handle_connect(self)
  536.         self.putrequest('GET', self._url)
  537.         self.endheaders()
  538.         self.getresponse()
  539.  
  540.  
  541. if __name__ == '__main__':
  542.     if len(sys.argv) < 4:
  543.         print 'Usage:  asynchttp.py <host> <port> <request>'
  544.         print "\t\tUsing www.google.com 80 '/'"
  545.         sys.argv[1:] = [
  546.             'www.google.com',
  547.             '80',
  548.             '/']
  549.     
  550.     tester = __test_AsyncHTTPConnection(sys.argv[1], int(sys.argv[2]), sys.argv[3])
  551.     tester.set_debuglevel(1)
  552.     tester.connect()
  553.     asyncore.loop()
  554.     if not hasattr(tester, 'response'):
  555.         print 'No rsponse'
  556.         sys.exit(-1)
  557.     
  558.     print 'results %s %d %s' % (tester.response.version, tester.response.status, tester.response.reason)
  559.     print 'headers:'
  560.     for hdr in tester.response.msg.headers:
  561.         print '%s' % string.strip(hdr)
  562.     
  563.     if tester.response.status == 200:
  564.         print 'body:'
  565.         print tester.response.body
  566.     
  567.  
  568.